
// import * as d3 from "../lib/d3.js";
import * as d3 from "d3";
import {$} from "../util/seq.js";
import {handleAsChord} from "./keyboard.js";
import {findIndex} from "underscore";
import {clickOn, firstClickable, lastClickable, nextClickable} from "./clickable.js";
import {restoreSessionStore} from "../framework/sessionStore.js";
import {restoreSharedStore} from "../framework/sharedStore.js";
import {restoreModalStore} from "../framework/modalStore.js";

export function defineKeyboardShortcuts(sharedStore, sessionStore, modalStore, tooltipController, inputController) {

    function clearDialog() {
        return (
            // modals
            modalStore.save({show_date_chooser: false, show_settings: false}) ||
            // tooltip
            tooltipController.hideTooltip() ||
            // notice
            sessionStore.save({notice: undefined}) ||
            // status
            sessionStore.save({status: undefined, error: undefined}) ||
            // spotlight
            sharedStore.save({spotlight_coords: undefined}) ||
            // earth menu
            sessionStore.save({show_menu: false}) ||
            // cta
            sessionStore.save({show_cta: false})
        );
    }

    const pressureLevels = d3.select("[data-name=z_level]").selectAll("button").nodes();

    function pressureIndex() {
        const {mode, z_level} = sharedStore.getAll();
        const i = mode === "air" ? findIndex(pressureLevels, node => node.dataset.name === z_level) : NaN;
        return i < 0 ? NaN : i;
    }

    function toggleDir() {
        const html = d3.select("html");
        const dir = html.property("dir");
        html.property("dir", dir === "ltr" ? "rtl" : "ltr");
        return true;
    }

    function toggleGrayscale() {
        const html = d3.select("html");
        const flag = html.classed("a11y-tests-grayscale");
        html.classed("a11y-tests-grayscale", !flag);
        return true;
    }

    function restore() {
        localStorage.clear();
        restoreSharedStore();
        restoreSessionStore();
        restoreModalStore();
        return true;
    }

    function interpretKeyDown(chord) {
        switch (chord) {
            case "Escape":      return clearDialog();
            case "Alt-Ø":
            case "Alt-O":       return toggleDir();
            case "Alt-Shift-˝":
            case "Alt-G":       return toggleGrayscale();
            case "Alt-Shift-˛":
            case "Alt-X":       return restore();
        }
    }

    function interpretKeyPress(chord) {
        switch (chord) {
            case "e": return clickOn("[data-name=earth]");
            case "I": return clickOn(lastClickable(pressureLevels));
            case "i": return clickOn(nextClickable(pressureLevels, pressureIndex(), 1));
            case "m": return clickOn(nextClickable(pressureLevels, pressureIndex(), -1));
            case "M": return clickOn(firstClickable(pressureLevels));
            case "n": return clickOn("[data-name=nav-now]");
            case "C": return clickOn("[data-name=show-date-chooser]");
            case "J": return clickOn("[data-name=nav-prev2]");
            case "j": return clickOn("[data-name=nav-prev1]");
            case "k": return clickOn("[data-name=nav-next1]");
            case "K": return clickOn("[data-name=nav-next2]");
            case "g": return clickOn("[data-name=toggle-grid]");
            case "p": return clickOn("[data-name=toggle-animation]");
            case "H": return clickOn("[data-name=toggle-hd]");
            case "d": return inputController.hotkey("zoom", 1.003);
            case "D": return inputController.hotkey("zoom", 1.05);
            case "x": return inputController.hotkey("zoom", 0.997);
            case "X": return inputController.hotkey("zoom", 0.95);
            case "z": return inputController.hotkey("up", 1);
            case "Z": return inputController.hotkey("up", 8);
            case "w": return inputController.hotkey("down", 1);
            case "W": return inputController.hotkey("down", 8);
            case "s": return inputController.hotkey("left", 1);
            case "S": return inputController.hotkey("left", 8);
            case "a": return inputController.hotkey("right", 1);
            case "A": return inputController.hotkey("right", 8);
            case "T": return clickOn("[data-name=show-settings]");

            // Never bind to keys used for search in various browsers:  /.',
            // Never bind to these keys: http://stackoverflow.com/questions/9612458/hot-keys-to-avoid
        }
    }

    d3.select("body")
        .on($`keydown`, handleAsChord(interpretKeyDown))
        .on($`keypress`, handleAsChord(interpretKeyPress));
}
